
const { ProcessMgr } = require("./processMgr");

const BettingType = {
    AT_THE_SAME_TIME: 0,       // 同时下注
    TAKE_TURNS_ONE_ROUND: 1,   // 轮流下注，下一轮
    TAKE_TURNS_BANKER: 2,      // 轮流下注，从庄家下到庄家
    TAKE_TURNS: 3,             // 轮流下注，下到不能下
}

class BettingProcessMgr extends ProcessMgr {
    constructor() {
        super();
        this.bettingType = null;
        this.banker = null;
        this.scoreBettings = {};
        this.bettingTime = 0;
        this.turnGamber = null;
        this.turnRound = 0;
        this.eliminateGambers = {};
        this.timerId = null;
        this.netMgr = null;
    }

    setBettingTime(bettingTime) {
        this.bettingTime = bettingTime;
    }

    setBanker(banker) {
        this.banker = banker;
    }

    getBanker() {
        return this.banker;
    }

    setBettingType(type) {
        this.bettingType = type;
    }

    doAction() {
        if (this.bettingType == BettingType.AT_THE_SAME_TIME) {
            this.timerId = setTimeout(function() {
                this.doNextAction();
            }, this.bettingTime * 1000);
        } else {
            this.turnRound = 0;
            this.turnGamberBetting(this.banker);
        }
    }

    defaultBetting(seatIndex) {
        this.onBetting(seatIndex, 0);
    }

    onBetting(seatIndex, value) {
        if (this.bettingType != BettingType.AT_THE_SAME_TIME) {
            // 不是同时下注，要检查是否轮到该玩家下注
            if (seatIndex != this.turnGamber) return;
            if (seatIndex == this.banker) {
                this.turnRound += 1;
            }
        } else {
            // 同时下注的，只能下一次
            if (this.scoreBettings[seatIndex] != null) return;
        }
        if (this.timerId) {
            clearTimeout(this.timerId);
        }
        // TODO:检查操作是否合法（比如炸金花第一轮不能比牌，但是客户端却发了这个指令）
        if (!this.isOperateLegal(seatIndex, value)) {
            return;
        }
        // TODO:检查下注金额是否正确
        if (!this.isCoinsEnough(seatIndex, value)) {
            return;
        }
        this.betting(seatIndex, value);

        if (this.isBettingFinish()) {
            this.doNextAction();
        } else {
            if (type != BettingType.AT_THE_SAME_TIME) {
                var nextGamber = this.seatMgr.getNextGamber(this.turnGamber);
                this.turnGamberBetting(nextGamber);
            }
        }
    }

    betting(seatIndex, value) {
        if (this.scoreBettings[seatIndex] == null) {
            this.scoreBettings[seatIndex] = 0;
        }
        this.scoreBettings[seatIndex] += value;
    }
    
    isOperateLegal(seatIndex, value) {
        return true;
    }

    isCoinsEnough(seatIndex, value) {
        return true;
    }

    turnGamberBetting(seatIndex) {
        this.turnGamber = seatIndex;
        var self = this;
        this.timerId = setTimeout(function() {
            self.defaultBetting(this.turnGamber);
        }, this.bettingTime * 1000);
    }

    isBettingFinish() {
        if (this.bettingType == BettingType.TAKE_TURNS_ONE_ROUND) {
            if (this.turnRound == 1 && this.seatMgr.getNextGamber(this.turnGamber) == this.banker) {
                return true;
            }
            return false;
        } else if (this.bettingType == BettingType.TAKE_TURNS_BANKER) {
            if (this.turnRound > 1 && this.turnGamber == this.banker) {
                return true;
            }
            return false;
        } else if (this.bettingType == BettingType.AT_THE_SAME_TIME) {
            var gamberIndexs = this.seatMgr.getGamberIndexs();
            for (let i = 0; i < gamberIndexs.length; ++i) {
                if (this.scoreBettings[gamberIndexs[i]] != null) {
                    return false;
                }
            }
            return true;
        } else if (this.bettingType == BettingType.TAKE_TURNS) {
            var count = 0;
            var gamberIndexs = this.seatMgr.getGamberIndexs();
            for (let i = 0; i < gamberIndexs.length; ++i) {
                if (!this.eliminateGambers[gamberIndexs[i]]) {
                    count += 1;
                }
            }
            return count == 1;
        }
    }

    getScoreBettings() {
        return this.scoreBettings;
    }
}

exports.BettingType = BettingType;
exports.BettingProcessMgr = BettingProcessMgr;